package com.wh.wisdomsite.xbox.zywl.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.jiangshikun.parrot.dao.RedisBaseDao;
import com.jiangshikun.parrot.dao.StringDao;
import com.wh.wisdomsite.xbox.common.Constants;
import com.wh.wisdomsite.xbox.common.reponse.CommonResult;
import com.wh.wisdomsite.xbox.core.XboxException;
import com.wh.wisdomsite.xbox.pojo.zywl.GetGateInfoOut;
import com.wh.wisdomsite.xbox.pojo.zywl.GetPushDataOut;
import com.wh.wisdomsite.xbox.utils.Const;
import com.wh.wisdomsite.xbox.utils.server.connToserver_HttpClientClose;
import com.wh.wisdomsite.xbox.zywl.dao.ZywlGateGroupMapper;
import com.wh.wisdomsite.xbox.zywl.dao.ZywlGateMapper;
import com.wh.wisdomsite.xbox.zywl.entity.ZywlGate;
import com.wh.wisdomsite.xbox.zywl.entity.ZywlGateGroup;
import com.wh.wisdomsite.xbox.zywl.service.IZywlGateGroupService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.*;

/**
 * 闸机组ServiceImpl
 * @author 蔡道行
 * @version V1.0
 * @date 16:54 2019/2/20
 * @Copyright 公司版权所有
 * @Company 贵州万华科技有限公司Copyright (c) 2014
 */
@Service("ywlGateGroupService")
@Transactional(rollbackFor = {Exception.class,RuntimeException.class})
public class IZywlGateGroupServiceImpl extends ServiceImpl<ZywlGateGroupMapper,ZywlGateGroup> implements IZywlGateGroupService {

    private static final Log logger = LogFactory.getLog(IZywlGateGroupServiceImpl.class);

    @Autowired
    private ZywlGateGroupMapper zywlGateGroupMapper;

    @Autowired
    private ZywlGateMapper zywlGateMapper;

    private StringDao stringDao = RedisBaseDao.getStringDao();

    @Override
    public CommonResult sycGateInfo() {
        CommonResult commonResult = new CommonResult();
        try{
            //接口查询结果
            String json = connToserver_HttpClientClose.sendPostRequest(Const.ZYWL_GETGATEINFO, null);
            GetGateInfoOut getGateInfoOut = JSONObject.parseObject(json, GetGateInfoOut.class);
            List<ZywlGateGroup> gateGroups = getGateInfoOut.getTransDictionaryList();
            //TEST START
//            //删除测试
//            gateGroups.remove(0);
//            //更新测试
//
//            gateGroups.get(0).setUpdateTime(new  Date(gateGroups.get(0).getUpdateTime().getTime() + 1000));
//            gateGroups.get(0).setTransCode(new String[] {
//                    "101","102","103"
//            });
            //TEST END
            //将接口查询获取到的所有闸机组的ID放入map中
            Map<String, ZywlGateGroup> gateGroupMap = new HashMap<>();
            for(ZywlGateGroup zywlGateGroup : gateGroups){
                gateGroupMap.put(zywlGateGroup.getId(), zywlGateGroup);
            }

            //从redis中获取已储存的闸机组信息
            Map<String, Object> gateGroupMapInRedis = JSONObject.parseObject(stringDao.getValue("gateGroupMapInRedis"), Map.class);
            //若查询不出结果，则从数据库中查询
            if(gateGroupMapInRedis == null || gateGroupMapInRedis.isEmpty()){
                gateGroupMapInRedis = new HashMap<>();
                EntityWrapper<ZywlGateGroup> ew = new EntityWrapper<>();
                ew.setEntity(new ZywlGateGroup());
                List<ZywlGateGroup> zywlGateGroups = zywlGateGroupMapper.selectList(ew);
                for(ZywlGateGroup zywlGateGroup : zywlGateGroups){
                    gateGroupMapInRedis.put(zywlGateGroup.getId(), zywlGateGroup);
                }
            }

            //判断是否有新的闸机组信息，进行储存操作
            if(gateGroupMapInRedis == null || gateGroupMapInRedis.isEmpty()){
                for(ZywlGateGroup zywlGateGroup : gateGroups){
                    insert(zywlGateGroup);
                    gateGroupMapInRedis.put(zywlGateGroup.getId(), zywlGateGroup);
                }
            }else{
                for(ZywlGateGroup zywlGateGroup : gateGroups){
                    //判断是否在redis的缓存中不存在，若不存在则储存
                    if(!gateGroupMapInRedis.containsKey(zywlGateGroup.getId())){
                        insert(zywlGateGroup);
                        gateGroupMapInRedis.put(zywlGateGroup.getId(), zywlGateGroup);
                    }else{
                        Object obj = gateGroupMapInRedis.get(zywlGateGroup.getId());
                        JSONObject zywlGateGroupInRedis;
                        if(obj instanceof ZywlGateGroup){
                            zywlGateGroupInRedis = JSONObject.parseObject(JSONObject.toJSONString(obj));
                        }else{
                            zywlGateGroupInRedis = (JSONObject)obj;
                        }

                        //存在需要判断是否有更新
                        if(zywlGateGroup.getUpdateTime() != null && zywlGateGroupInRedis.getString("updateTime") != null
                                && zywlGateGroup.getUpdateTime().compareTo(new Date(Long.parseLong(zywlGateGroupInRedis.getString("updateTime")))) != 0){
                            //判断更新时间有变化的闸机组信息，进行更新操作
                            updateById(zywlGateGroup);
                            gateGroupMapInRedis.put(zywlGateGroup.getId(), zywlGateGroup);
                        }
                    }
                }
            }
            //判断已被删除的闸机，进行删除操作
            if(gateGroupMapInRedis != null && !gateGroupMapInRedis.isEmpty()){
                List<String> deleteKey = new ArrayList<>();
                for(String key :gateGroupMapInRedis.keySet()){
                    //遍历redis中的缓存闸机，查询是否有已被删除的
                    if(!gateGroupMap.containsKey(key)){
                        //若不存在，则在缓存和数据库中进行删除操作
                        deleteById(key);
                        deleteKey.add(key);
                    }
                }
                //将需要删除的key从缓存中删除
                if(deleteKey.size() > 0){
                    for(String key : deleteKey){
                        gateGroupMapInRedis.remove(key);
                    }
                }
            }
            //全部操作结束后，更新redis
            stringDao.save("gateGroupMapInRedis", JSONObject.toJSONString(gateGroupMapInRedis), 0);
            //成功，对返回结果进行处理
            commonResult.setCode(Constants.CODE_SUCCESS);
            commonResult.setMessage("同步闸机信息成功");
            commonResult.setResult(JSONObject.parse(json));
        }catch (Exception e){
            e.printStackTrace();
            throw new XboxException(e.getMessage());
        }
        return commonResult;
    }

    @Override
    public boolean insert(ZywlGateGroup zywlGateGroup) {
        boolean result;
        ZywlGateGroup forSearch = selectById(zywlGateGroup.getId());
        if(forSearch == null){
            //储存gateGroup
            result = zywlGateGroupMapper.insert(zywlGateGroup) > 0;
        }else{
            //更新gateGroup
            result = zywlGateGroupMapper.updateById(zywlGateGroup) > 0;
        }
        //储存gate
        updateGates(zywlGateGroup);
        return result;
    }

    @Override
    public boolean deleteById(Serializable id) {
        boolean result;
        //先删除gateGroup本身
        result = zywlGateGroupMapper.deleteById(id) > 0;
        //再删除该gateGroup下的所有闸机
        EntityWrapper<ZywlGate> ew = new EntityWrapper<>();
        ew.setEntity(new ZywlGate());
        ew.eq("ggId", id);
        zywlGateMapper.delete(ew);
        return result;
    }

    @Override
    public boolean updateById(ZywlGateGroup entity) {
        updateGates(entity);
        return super.updateById(entity);
    }

    private void updateGates(ZywlGateGroup zywlGateGroup){
        //删除子表的所有闸机，更新其闸机信息
        EntityWrapper<ZywlGate> ew = new EntityWrapper<>();
        ew.setEntity(new ZywlGate());
        ew.eq("ggId", zywlGateGroup.getId());
        zywlGateMapper.delete(ew);

        //遍历闸机ID，储存闸机信息
        String[] transCodes = zywlGateGroup.getTransCode();
        if(transCodes != null && transCodes.length > 0){
            for(String transCode : transCodes){
                ZywlGate zywlGate = new ZywlGate();
                zywlGate.setTransCode(transCode);
                zywlGate.setGgId(zywlGateGroup.getId());
                zywlGateMapper.insert(zywlGate);
            }
        }
    }
}
